package com.chenille.tools.extens

import android.app.Activity
import android.content.Context
import android.widget.Toast
import androidx.annotation.ColorRes
import androidx.annotation.DimenRes
import androidx.core.content.ContextCompat
import androidx.databinding.Observable
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import autodispose2.AutoDispose
import autodispose2.AutoDisposeConverter
import autodispose2.FlowableSubscribeProxy
import autodispose2.SingleSubscribeProxy
import autodispose2.androidx.lifecycle.AndroidLifecycleScopeProvider
import com.chenille.tools.BuildConfig.DEBUG
import com.chenille.tools.util.KLog
import com.chenille.tools.util.ToastUtil
import io.reactivex.rxjava3.android.MainThreadDisposable
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException

/**
 * @desc
 * @contact   cnhttt@163.com
 * @author  couldxtra
 * @time  2022/3/8 12:30 上午
 * @version v1.0
 * @update: [序号:1][日期YYYY-MM-DD:2022/3/8] [更改人姓名:F][变更描述:create]
 */

//获取color
fun Activity.getCompactColor(@ColorRes colorRes: Int): Int = ContextCompat.getColor(this, colorRes)

//显示toast
fun Activity.toast(
    msg: String, type: ToastUtil.Type = ToastUtil.Type.POINT
) {
    when (type) {
        ToastUtil.Type.POINT -> ToastUtil.showCus(this, msg,type)
        ToastUtil.Type.SUCCEED -> ToastUtil.showCus(this, msg,type)
        ToastUtil.Type.ERROR -> ToastUtil.showCus(this, msg,type)
        ToastUtil.Type.WARNING -> ToastUtil.showCus(this, msg,type)
        ToastUtil.Type.OTHER -> ToastUtil.showCus(this, msg,type)
    }
}
fun Activity.dispatchFailure(error: Throwable?) {
    error?.let {
        if (DEBUG) {
            it.printStackTrace()
        }
      if (error is SocketTimeoutException) {
            it.message?.let { toast("网络连接超时", ToastUtil.Type.ERROR) }
        } else if (it is UnknownHostException || it is ConnectException) {
            //网络未连接
            it.message?.let { toast("网络未连接", ToastUtil.Type.ERROR) }
        } else {
            it.message?.let { toast(it, ToastUtil.Type.ERROR) }
        }
    }
}




fun Activity.dpToPx(@DimenRes resID: Int): Int = this.resources.getDimensionPixelOffset(resID)
fun Context.dpToPx(@DimenRes resID: Int): Int = this.resources.getDimensionPixelOffset(resID)



fun Any.logD(msg: String?) {
    if (DEBUG) {
        msg?.let { KLog.d(javaClass.simpleName, it) }
    }
}
fun Any.logE(msg: String?) {
    if (DEBUG) {
        msg?.let { KLog.e(javaClass.simpleName, it) }
    }
}


fun <T> Flowable<T>.async(withDelay: Long = 0): Flowable<T> =
    this.subscribeOn(Schedulers.io()).delay(
        withDelay,
        java.util.concurrent.TimeUnit.MILLISECONDS
    ).observeOn(AndroidSchedulers.mainThread())

fun <T> Single<T>.async(withDelay: Long = 0): Single<T> =
    this.subscribeOn(Schedulers.io()).delay(
        withDelay,
        java.util.concurrent.TimeUnit.MILLISECONDS
    ).observeOn(
        AndroidSchedulers.mainThread()
    )


fun <T> Single<T>.bindLifeCycle(owner: LifecycleOwner): SingleSubscribeProxy<T> =
    this.to(
        AutoDispose.autoDisposable(
            AndroidLifecycleScopeProvider.from(
                owner,
                Lifecycle.Event.ON_DESTROY
            )
        )
    )

fun <T> Flowable<T>.bindLifeCycle(owner: LifecycleOwner): FlowableSubscribeProxy<T> =
    this.to(
        AutoDispose.autoDisposable(
            AndroidLifecycleScopeProvider.from(
                owner,
                Lifecycle.Event.ON_DESTROY
            )
        )
    )


//////////////////////////LiveData///////////////////////////////////

fun <T> MutableLiveData<T>.set(t: T?) = this.postValue(t)
fun <T> MutableLiveData<T>.get() = this.value
fun <T> MutableLiveData<T>.get(t: T): T = get() ?: t
fun <T> MutableLiveData<T>.init(t: T) = MutableLiveData<T>().apply {
    postValue(t)
}
fun <T> LiveData<T>.toFlowable(): Flowable<T> = Flowable.create({ emitter ->
    val observer = Observer<T> { data ->
        data?.let { emitter.onNext(it) }
    }
    observeForever(observer)

    emitter.setCancellable {
        object : MainThreadDisposable() {
            override fun onDispose() = removeObserver(observer)
        }
    }
}, BackpressureStrategy.LATEST)

//////////////////////////DataBinding///////////////////////////////////
fun <T> ObservableField<T>.toFlowable(): Flowable<T> = Flowable.create({ emitter ->
    val observer = object : Observable.OnPropertyChangedCallback() {
        override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
            get()?.let { emitter.onNext(it) }
        }
    }
    addOnPropertyChangedCallback(observer)

    emitter.setCancellable {
        object : MainThreadDisposable() {
            override fun onDispose() = removeOnPropertyChangedCallback(observer)
        }
    }
}, BackpressureStrategy.LATEST)

fun ObservableBoolean.toFlowable(): Flowable<Boolean> = Flowable.create({ emitter ->
    val observer = object : Observable.OnPropertyChangedCallback() {
        override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
            emitter.onNext(get())
        }
    }
    addOnPropertyChangedCallback(observer)

    emitter.setCancellable {
        object : MainThreadDisposable() {
            override fun onDispose() = removeOnPropertyChangedCallback(observer)
        }
    }
}, BackpressureStrategy.LATEST)
